﻿namespace MaciejGrabek.WebAPITools
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.IO;

    public class ServiceCaller
    {
        public string ServiceUrl { get; private set; }

        public ServiceCaller(string serviceUrl)
        {
            ServiceUrl = serviceUrl.TrimEnd(new char[] { '/' });
        }

        /// <summary>
        /// Calls the services.
        /// </summary>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <typeparam name="TBody">The type of the body.</typeparam>
        /// <param name="callActionUrl">The call URL.</param>
        /// <param name="body">The body of request.</param>
        /// <param name="callMethod">The call method.</param>
        /// <param name="headers">The headers for request.</param>
        /// <returns>Result of call</returns>
        public TResult CallService<TResult, TBody>(string callActionUrl, TBody body, CallMethod callMethod, Dictionary<string, string> headers)
        {
            WebResponse response = GetResponse(callActionUrl, body, callMethod, headers);
            TResult result = JsonSerializationHelper.Deserialize<TResult>(response.GetResponseStream());
            return result;
        }

        /// <summary>
        /// Calls the services and returns string response.
        /// </summary>
        /// <typeparam name="TBody">The type of the body.</typeparam>
        /// <param name="callActionUrl">The call URL.</param>
        /// <param name="body">The body of request.</param>
        /// <param name="callMethod">The call method.</param>
        /// <param name="headers">The headers for request.</param>
        /// <returns>Result of call</returns>
        public string CallServicesForString<TBody>(string callActionUrl, TBody body, CallMethod callMethod, Dictionary<string, string> headers)
        {
            WebResponse response = GetResponse(callActionUrl, body, callMethod, headers);
            StreamReader sr = new StreamReader(response.GetResponseStream());
            string result = sr.ReadToEnd();
            return result;
        }

        private WebResponse GetResponse<TBody>(string callActionUrl, TBody body, CallMethod callMethod, Dictionary<string, string> headers)
        {
            WebRequest request = WebRequest.Create(string.Format("{0}/{1}", ServiceUrl, callActionUrl));
            request.Method = callMethod.ToString().ToUpper();
            request.ContentType = "application/json";
            foreach (KeyValuePair<string, string> header in headers)
            {
                request.Headers.Add(header.Key, header.Value);
            }

            if (callMethod == CallMethod.Post || callMethod == CallMethod.Put)
            {
                Stream dataStream = request.GetRequestStream();
                string jsonRequestBody = JsonSerializationHelper.Serialize<TBody>(body);
                byte[] byteArray = Encoding.UTF8.GetBytes(jsonRequestBody);
                dataStream.Write(byteArray, 0, byteArray.Length);
                dataStream.Close();
            }

            WebResponse response = request.GetResponse();
            return response;
        }
    }
}
